package client

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/baizhige/go-server-tempalte/common/constant"
	"gitee.com/baizhige/go-server-tempalte/common/log"
	"gitee.com/baizhige/go-server-tempalte/common/redis"
	"gitee.com/baizhige/go-server-tempalte/util/random"
	"github.com/gin-gonic/gin"
)

//security.go 对外提供能力

// 生成通信密钥 缓存通信密钥
func GenerateKey(traceID string, c *gin.Context) (key string, err error) {
	//获取客户端ID
	clientId := c.GetHeader(constant.HeaderClientId)
	if clientId == "" {
		log.ErrorTF(traceID, "Client id not find")
		err = constant.ErrClientIdNotFind
		return
	}
	//读取密文请求体
	encryptReq := &EncryptReq{}
	err = c.ShouldBindJSON(encryptReq)
	if err != nil {
		log.ErrorTF(traceID, "EncryptReq read error: %s", err)
		err = constant.ErrClientKeyParamInvalid
		return
	}
	marshal, _ := json.Marshal(encryptReq)
	log.InfoTF(traceID, "generate key req:%s", string(marshal))

	//获取明文请求体
	reqBts, err := rSADecryptBase64(encryptReq.Data)
	if err != nil {
		log.ErrorTF(traceID, "EncryptReq decrypt error: %s", err)
		err = constant.ErrClientKeyParamInvalid
		return
	}
	req := new(generateKeyReq)
	err = json.Unmarshal(reqBts, req)
	if err != nil {
		log.ErrorTF(traceID, "json.Unmarshal req error: %s,content:%s", err, string(reqBts))
		err = constant.ErrClientKeyParamInvalid
		return
	}
	trustKey := req.TrustKey
	if len(trustKey) != 16 {
		log.ErrorTF(traceID, "req trustKey invalid,len:%v,requie 16", len(trustKey))
		err = constant.ErrClientTrustKeyInvalid
		return
	}
	//生成通信密钥，通过互信密钥加密返回
	cryptoRand := random.Crypto(16) //长度为16的字符串 - 通信密钥
	//缓存通信秒
	redisKey := fmt.Sprintf(constant.CacheClientSecretKey, clientId)
	err = redis.Set(redisKey, cryptoRand, 0)
	if err != nil {
		log.ErrorTF(traceID, "client key into redis fail:%v,key:%s", err, redisKey)
		err = constant.ErrRedisOperation
		return
	}
	key, err = aESBase64Enc(cryptoRand, trustKey)
	if err == nil {
		log.InfoTF(traceID, "generate key success :%s", key)
	}
	return
}

// 加密数据
func Encrypt(traceID, data string, c *gin.Context) (res string, err error) {
	//获取客户端key
	clientKey, err := getClientKey(traceID, c)
	if err != nil {
		if errors.Is(err, redis.ErrNotFound) {
			err = constant.ErrClientKeyNotFind
		}
		return
	}

	//加密数据
	return aESBase64Enc(data, clientKey)

}

// 解密数据
func Decoder(traceID, data string, c *gin.Context) (res string, err error) {
	//获取客户端key
	clientKey, err := getClientKey(traceID, c)
	if err != nil {
		if errors.Is(err, redis.ErrNotFound) {
			err = constant.ErrClientKeyNotFind
		}
		return
	}
	//解密
	log.InfoTF(traceID, "origin data is:%s", data)
	return aESBase64Dec(data, clientKey)
}
